package cn.com.bluemoon.daps.system.auth;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;

import javax.annotation.Nullable;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author Jarod.Kong
 */
public class JwtUtils {
    public static final String businessId = "businessId";
    public static final String certificateKey = "certificateKey";
    private static final String SECRET = "8606506E1E1644B3BEC3E3FEA63E8341";
    private static final long EXPIRATION_DAYS = 7;
    public static String confirmStatus = "confirmStatus";

    private JwtUtils() {
    }

    public static String createToken(Map<String, Object> customHeaderMap) {
        return createToken(customHeaderMap, EXPIRATION_DAYS);
    }

    public static String createToken(Map<String, Object> customHeaderMap, @Nullable Long expireDay) {
        if (customHeaderMap == null) {
            throw new RuntimeException("请填写自定义token信息");
        }
        if (expireDay == null) {
            expireDay = EXPIRATION_DAYS;
        }
        Date expireDate = new Date(System.currentTimeMillis() + TimeUnit.DAYS.toMillis(expireDay));
        Map<String, Object> map = new HashMap<>();
        map.put("alg", "HS256");
        map.put("typ", "JWT");
        String token = JWT.create().withHeader(map)
                .withClaim(businessId, Objects.toString(customHeaderMap.get(businessId), null))
                .withClaim(certificateKey, Objects.toString(customHeaderMap.get(certificateKey), null))
                .withClaim(confirmStatus, String.valueOf(customHeaderMap.get(confirmStatus)))
                .withExpiresAt(expireDate)
                .withIssuedAt(new Date())
                .sign(Algorithm.HMAC256(SECRET));
        return token;
    }

    public static DecodedJWT decodedJWT(String token) {
        DecodedJWT jwt;

        try {
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();
            jwt = verifier.verify(token);
        } catch (Exception e) {
            return null;
        }

        return jwt;
    }

    public static boolean verifyToken(String token, @Nullable Date currentDate) {
        if (currentDate == null) {
            currentDate = new Date();
        }
        DecodedJWT decodedJWT = decodedJWT(token);
        Date expiresAt = null;
        if (decodedJWT != null) {
            expiresAt = decodedJWT.getExpiresAt();
            return !currentDate.after(expiresAt);
        }
        return false;
    }

    public static Map<String, Object> decodedToken(String token) {
        DecodedJWT jwt = decodedJWT(token);
        Map<String, Object> r = new HashMap<>();
        if (jwt != null) {
            Map<String, Claim> claims = jwt.getClaims();
            claims.forEach((key, value) -> r.put(key, value.as(Object.class)));
        }
        return r;
    }


    public static void main(String[] args) {
        Map<String, Object> map = new HashMap<>();
        map.put("businessId", "1");
        map.put("certificateKey", "80560490");
        String token = createToken(map);
        System.out.println(token);
        System.out.println(verifyToken(token, new Date()));
        Map<String, Object> stringClaimMap = decodedToken(token);
        System.out.println(stringClaimMap);
        boolean b = verifyToken("1", new Date());
        System.out.println(b);
    }

}
